#ifndef _XMLDATA_H_
#define _XMLDATA_H_


#include "Common.h"
#include "String.h"
#include "Resource.h"
#include "tinyxml/tinyxml.h"


typedef struct _xml_item_tag_
{
        uint32  model_id;
        uint16  flag;   //保留
        uint32  id;     //任务资源ID
        String  name;   //任务名字
        String  desc;   //任务描述
        uint8   lv;     //任务等级
        uint8   lv_ext; //任务强化等级
        uint32  num;    //任务的数量
        uint32  script_id;      //创建任务需要的脚本ID
	uint8	group;	//任务组

        inline void    initialize(void)
        {
                model_id = 0;
                flag = 0;
                id = 0;
                name = "unkown name";
                desc = "";
                lv = 0;
                lv_ext = 0;
		num  = 0;
                script_id = 0;
		group = 0;
        }

	inline _xml_item_tag_ & operator = ( const _xml_item_tag_& xml_item )
        {
		model_id = xml_item.model_id;
                flag = xml_item.flag;
                id = xml_item.id;
                name = xml_item.name;
                desc = xml_item.desc;
                lv = xml_item.lv;
                lv_ext = xml_item.lv_ext;
		num = xml_item.num;
                script_id = xml_item.script_id;
		group = xml_item.group;

                return *this;
        }

        _xml_item_tag_(void)
        {
                initialize();                   
        }
}xml_item_st;


//for xmldata inner lock
#define WGS_XMLDATA_INNER_MUTEX_NAME xmldata_inner_mutex
#define WGS_XMLDATA_INNER_MUTEX mutable boost::mutex WGS_XMLDATA_INNER_MUTEX_NAME;
#define WGS_XMLDATA_INNER_LOCK		boost::lock_guard<boost::mutex> wgsXMLDataInnerMutexLock(WGS_XMLDATA_INNER_MUTEX_NAME);

class SERVER_DECL XMLData	
{
public:
	enum  XMLDataType
	{
		XMLDataTypeNone		 = 0,
		XMLDataTypeUInt		 = 1,	//无符号整型
		XMLDataTypeInt		 = 2, //符号整型
		XMLDataTypeFloat	 = 3,	//浮点
		XMLDataTypeString	 = 4,	//字符串
		XMLDataTypeItem		 = 5,	//任务类型
		XMLDataTypeUnkown	 = 255	//未知类型
	};

	enum XMLDataMode
	{
		XMLDataModeNone		= 0,	//无效模式
		XMLDataModeServer	= 1,	//服务器设置
		XMLDataModeClient	= 2,	//客户端设置
		XMLDataModeOther	=255	//其他模式
	};

protected:
	WGS_XMLDATA_INNER_MUTEX
	
	void	*	m_data;
	XMLDataType	m_type;
	String		m_desc;
	bool		m_dirty;
	String		m_xml;
	String		m_name;
	XMLDataMode	m_mode;
	



	void	Clear(void);
	void buildXML(void);


	XMLData(void):m_data(0),m_type(XMLDataTypeNone),m_desc(""),m_xml(""),m_name("")
	{
		WGS_XMLDATA_INNER_LOCK

		m_mode = XMLDataModeNone;
		m_dirty = false;
	}

public:
	template< typename Y > XMLData(const Y & data,const String & name = "",const String & desc  = "" ,const XMLDataMode & mode = XMLData::XMLDataModeServer)
	{
		WGS_XMLDATA_INNER_LOCK

		m_dirty = true;
		m_xml = "";

		if(typeid(Y) == typeid(uint32))
		{
			m_type = XMLDataTypeUInt;
		}
		else if(typeid(Y) == typeid(int32))
			m_type = XMLDataTypeInt;
		else if(typeid(Y) == typeid(float))
			m_type = XMLDataTypeFloat;
		else if(typeid(Y) == typeid(String))
			m_type =  XMLDataTypeString;
		else if(typeid(Y) == typeid(xml_item_st))
			m_type = XMLDataTypeItem;
		else
		{
			m_type = XMLDataTypeUnkown;
			return;
		}

		
		m_data = new Y;
		*(static_cast<Y *>(m_data)) = data;
		
		if(name == "")
			m_name = typeid(Y).name();
		else
			m_name = name;	

		m_mode = mode;
		m_desc = desc;

	}

	XMLData(TiXmlElement * elm);

	virtual ~XMLData(); 

	inline	bool isNull(void)	{
		WGS_XMLDATA_INNER_LOCK		
		return m_data == NULL?true:false;
	}
	inline	void setNull(void)	{	Clear();	}

	const XMLDataType  getType(void)	{	
		WGS_XMLDATA_INNER_LOCK
		return m_type;	
	}

	const String  getDescrition(void)	{	
		WGS_XMLDATA_INNER_LOCK
		return m_desc;	
	}
	void	setDescrition(const String & desc)	{
		WGS_XMLDATA_INNER_LOCK
		m_desc = desc,m_dirty = true;	
	}

	const XMLDataMode  getMode(void)	{	
		WGS_XMLDATA_INNER_LOCK
		return m_mode;	
	}
	void setModel(const XMLDataMode & mode)	{
		if(m_mode == mode)
			return ;
		WGS_XMLDATA_INNER_LOCK
		m_mode = mode,m_dirty = true;
	}

	const bool  isDirty(void)	{	return m_dirty;	}

	const String  getName(void)		{	
		WGS_XMLDATA_INNER_LOCK
		return m_name;	
	}
	const String  getXML(void);

	XMLData& operator=(const uint32 & r);
	XMLData& operator=(const int32 & r);
	XMLData& operator=(const float & r);
	XMLData& operator=(const String & r);
	XMLData& operator=(const xml_item_st & r);

	template<typename Y> Y* Get()	{
		WGS_XMLDATA_INNER_LOCK
		return static_cast<Y * >(m_data);	
	}
	template<typename Y> void Set(const Y & r)
	{
		if(isNull())
			return ;

		WGS_XMLDATA_INNER_LOCK
		*(static_cast<Y *>(m_data)) = r;
		m_dirty = true;
	}

	template<typename Y> void operator >> (Y & r) { r = *Get<Y>(); }
	template<typename Y> void operator << (const Y & r) {  Set<Y>(r); }

};


//for xmldata inner lock
#define WGS_XMLDATASET_INNER_MUTEX_NAME xmldataset_inner_mutex
#define WGS_XMLDATASET_INNER_MUTEX mutable boost::mutex WGS_XMLDATASET_INNER_MUTEX_NAME;
#define WGS_XMLDATASET_INNER_LOCK		boost::lock_guard<boost::mutex> wgsXMLDataSetInnerMutexLock(WGS_XMLDATASET_INNER_MUTEX_NAME);


class SERVER_DECL XMLDataSet
{
protected:
	std::map<String,XMLData *> m_datas;
	String		m_fieldName;
	bool		m_loaded;
	ResourceProxy	m_resource;
	bool		m_dirty;
	String		m_xml;
	

	void	Clear(void);

	String BuildXML(void);
public:
	WGS_XMLDATASET_INNER_MUTEX

	XMLDataSet();
	//XMLDataSet(const ResourceProxy & resProxy,const String & fieldName);
	virtual ~XMLDataSet(void);

	//void	Load(void);
	void	Load(const ResourceProxy & resProxy,const String & fieldName);
	void	Load(const String & xmlData);
	void	Unload(void);
	void	Save(void);

	//得到XML数据
	XMLData *  getXMLData(const String & name);
	//是否存在XMLData
	bool	isPresented(const String & name);
	

	//从名字得到XMLData中的数据,失败返回0 指针
	template<typename Y> Y* Get(const String & name)
	{
		WGS_XMLDATASET_INNER_LOCK
		XMLData * data = getXMLData(name);
		if(data)
			return data->Get<Y>();
		else
			return 0;
	}
	//得到XMLData中的数据，设置成功返回true 否则返回false
	template<typename Y> bool Get(const String & name, Y & r)
	{
		WGS_XMLDATASET_INNER_LOCK
		XMLData * data = getXMLData(name);
		if(data)
		{
			r = *(data->Get<Y>());
			return true;
		}
		else
			return false;
	}

	//设置XMLData中的数据，设置成功返回true 否则返回false
	template<typename Y> bool Set(const String & name,const Y & r)
	{
		WGS_XMLDATASET_INNER_LOCK
		XMLData * data = getXMLData(name);
		if(data)
		{
			data->Set<Y>(r);
			return true;
		}
		else
			return false;
	}
			
	//设置XMLData中的数据，设置成功返回true 否则返回false
	template<typename Y> bool New(const String & name,const Y & r,const String & desc  = "",const XMLData::XMLDataMode  & mode = XMLData::XMLDataModeServer)
	{
		{
			WGS_XMLDATASET_INNER_LOCK
			XMLData * data = getXMLData(name);
			if(data)
			{
				data->Set<Y>(r);
				return true;
			}
		}

		addXMLData(new XMLData(r,name,desc,mode));	
		return true;
	}

	const String   getXML(void);

	std::map<String,XMLData *>	* getDatas(void)	{	return &m_datas;	}

	bool	isDirty(void);
	//添加XML数据项到集合中
	bool	addXMLData(XMLData * data);
	//从集合中移除
	bool	removeXMLData(const String & name);
	bool	removeXMLData(XMLData * data);
	

};

#endif
